#ifndef _TEST_INTERSECT_H_
#define _TEST_INTERSECT_H_
#include <cppunit/extensions/HelperMacros.h>

class Test_intersect : public CppUnit::TestFixture
{
	CPPUNIT_TEST_SUITE (Test_intersect);
	/* Co-planar test cases. 
	CPPUNIT_TEST (test_pol_pol_01);
	CPPUNIT_TEST (test_pol_pol_02);
	CPPUNIT_TEST (test_pol_pol_03);
	CPPUNIT_TEST (test_pol_pol_04);
	CPPUNIT_TEST (test_pol_pol_05);
	*/
	CPPUNIT_TEST (test_pol_pol_06);
	CPPUNIT_TEST (test_pol_pol_07);
	CPPUNIT_TEST (test_pol_pol_08);
	CPPUNIT_TEST (test_pol_pol_09);
	CPPUNIT_TEST (test_pol_pol_10);

	CPPUNIT_TEST (test_pol_pol_11);
	CPPUNIT_TEST (test_pol_pol_12);
	CPPUNIT_TEST (test_pol_pol_13);
	CPPUNIT_TEST (test_pol_pol_14);
	CPPUNIT_TEST (test_pol_pol_15);

	CPPUNIT_TEST_SUITE_END();

public :
	void setUp(){}
	void tearDown(){}

	/**
	 * Co-planar triangles. Vertex intersects vertex. 
	 */
	void test_pol_pol_01()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1.0), Value(1e-54));
			q1 = Vector<Value> (Value (1.0), Value(1.0), Value(1e-54));
			r1 = Vector<Value> (Value (1.718281828e-54), Value(0.103), Value(1e-54));

			p2 = Vector<Value> (Value (-1.0), Value(0.0), Value(1e-54));
			q2 = Vector<Value> (Value (1.718281828e-54), Value(0.103), Value(1e-54));
			r2 = Vector<Value> (Value (-1.0), Value(-1.0), Value(1e-54));

			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);
		}
//		CPPUNIT_ASSERT (POINT == res.res_type);
	}
	/**
	 * Co-planar triangles. Vertex intersects vertex. Silver triangles. 
	 */
	void test_pol_pol_02()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1.0), Value(1e54));
			q1 = Vector<Value> (Value (1.0), Value(1.0), Value(1e54));
			r1 = Vector<Value> (Value (1.718281828e-54), Value(1.03e128), Value(1e54));

			p2 = Vector<Value> (Value (-1.0), Value(0.0), Value(1e54));
			q2 = Vector<Value> (Value (1.718281828e-54), Value(1.03e128), Value(1e54));
			r2 = Vector<Value> (Value (-1.0), Value(-1.0), Value(1e54));

			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}
    /**
	 * Co-planar triangles. Vertex intersects vertex.  Circulate triangle vertex. 
	 */
	void test_pol_pol_03()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1.0), Value(1e54));
			q1 = Vector<Value> (Value (1.0), Value(1.0), Value(1e54));
			r1 = Vector<Value> (Value (1.718281828e-54), Value(1.03e128), Value(1e54));

			p2 = Vector<Value> (Value (-1.0), Value(0.0), Value(1e54));
			q2 = Vector<Value> (Value (1.718281828e-54), Value(1.03e128), Value(1e54));
			r2 = Vector<Value> (Value (-1.0), Value(-1.0), Value(1e54));

			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); polygon1.append_vertex(q1); polygon1.append_vertex(r1);
			polygon2.append_vertex(p2); polygon2.append_vertex(q2); polygon2.append_vertex(r2);
			CPPUNIT_ASSERT (true == predicate_polygon_polygon (polygon1, polygon2 ));		

			PolygonType polygon3 ; 
			polygon3.append_vertex(q2); polygon3.append_vertex(r2); polygon3.append_vertex(p2);  
			CPPUNIT_ASSERT (true == predicate_polygon_polygon (polygon1, polygon3 ));		

			PolygonType polygon4 ; 
			polygon4.append_vertex(r2); polygon4.append_vertex(p2); polygon4.append_vertex(q2);  
			CPPUNIT_ASSERT (true == predicate_polygon_polygon (polygon1, polygon4 ));		
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}

	/**
	 * Co-planar triangles. None-intersect. 
	 */
	void test_pol_pol_04()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1.0), Value(1e54));
			q1 = Vector<Value> (Value (1.0), Value(1.0), Value(1e54));
			r1 = Vector<Value> (Value (1.123456789e-54), Value(1.03e128), Value(1e54));

			p2 = Vector<Value> (Value (-1.0), Value(0.0), Value(1e54));
			q2 = Vector<Value> (Value (1.123456788e-54), Value(1.03e-128), Value(1e54));
			r2 = Vector<Value> (Value (-1.0), Value(-1.0), Value(1e54));

			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			CPPUNIT_ASSERT (false == predicate_polygon_polygon (polygon1, polygon2 ));
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}
	/**
	 * Co-planar triangles. Vertex intersect edges. 
	 */
	void test_pol_pol_05()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1e-54), Value(1e128));
			q1 = Vector<Value> (Value (1e-54), Value(1e-54), Value(1e128));
			r1 = Vector<Value> (Value (2e-54), Value(1e103), Value(1e128));

			p2 = Vector<Value> (Value (0.5e-54), Value(1e-54), Value(1e128));
			q2 = Vector<Value> (Value (3e-54), Value(-1e-54), Value(1e128));
			r2 = Vector<Value> (Value (4e-54), Value(-1e-54), Value(1e128));


			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));
			CPPUNIT_ASSERT (SEGMENT == res.res_type );
			CPPUNIT_ASSERT (res.segment.p0 == res.segment.p1);

//			CPPUNIT_ASSERT (true == predicate_polygon_polygon (polygon1, polygon2 ));
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}

	/**
	 * Non-intersect triangle. Parallel. One is above the other along z-axis. 
	 */
	void test_pol_pol_06()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1.0e54), Value(1e-54));
			q1 = Vector<Value> (Value (1.0e54), Value(1.0e54), Value(1e-54));
			r1 = Vector<Value> (Value (1.123456789e-54), Value(1.03e128), Value(1e-54));

			p2 = Vector<Value> (Value (0.0), Value(1.0e54), Value(-1e-54));
			q2 = Vector<Value> (Value (1.0e54), Value(1.0e54), Value(-1e-54));
			r2 = Vector<Value> (Value (1.123456789e-54), Value(1.03e128), Value(-1e-54));


			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			CPPUNIT_ASSERT (false == predicate_polygon_polygon (polygon1, polygon2 ));
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}

    /**
     * Non-coplanar triangles. Vertex intersect vertex. 
     * The intersection point is (1.718281828e-54, 0.103, 0);
     */
	void test_pol_pol_07()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1.0), Value(1e-54));
			q1 = Vector<Value> (Value (1.0), Value(1.0), Value(1e-54));
			r1 = Vector<Value> (Value (1.718281828e-54), Value(0.103), Value(0.0));

			p2 = Vector<Value> (Value (-1.0), Value(0.0), Value(0.0));
			q2 = Vector<Value> (Value (1.718281828e-54), Value(0.103), Value(0.0));
			r2 = Vector<Value> (Value (-1.0), Value(-1.0), Value(0.0));

			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));
			CPPUNIT_ASSERT (r1  == res.point );
			CPPUNIT_ASSERT (q2  == res.point);
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}

    /**
     * Non-coplanar triangles. Vertex intersect vertex. 
     * The intersection point is (1.718281828e-54, 0.103, 0);
     */
	void test_pol_pol_08()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1.0), Value(1e-54));
			q1 = Vector<Value> (Value (1.0), Value(1.0), Value(1e-54));
			r1 = Vector<Value> (Value (1.718281828e-54), Value(0.103), Value(0.0));

			p2 = Vector<Value> (Value (0.0), Value(1.0), Value(0));
			q2 = Vector<Value> (Value (1.0), Value(1.0), Value(0));
			r2 = Vector<Value> (Value (1.718281828e-54), Value(0.103), Value(0.0));


			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));
			CPPUNIT_ASSERT (POINT == res.res_type );
			CPPUNIT_ASSERT (r1 == res.point);
			CPPUNIT_ASSERT (r2 == res.point);
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}	
	}

	/**
	 * Non-coplanar triangles. Vertex intersect vertex silver triangles. 
	 */
	void test_pol_pol_09()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1e-54), Value(1e128));
			q1 = Vector<Value> (Value (1e-54), Value(-1e-54), Value(0.0));
			r1 = Vector<Value> (Value (2e-54), Value(1e103), Value(0.0));

			p2 = Vector<Value> (Value (2e-54), Value(1e103), Value(0.0));
			q2 = Vector<Value> (Value (3e-54), Value(1e-54), Value(0));
			r2 = Vector<Value> (Value (4e-54), Value(-1e-54), Value(0.0));


			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));
			CPPUNIT_ASSERT (POINT == res.res_type );
			CPPUNIT_ASSERT (r1 == res.point);
			CPPUNIT_ASSERT (p2 == res.point);

//			CPPUNIT_ASSERT (true == predicate_polygon_polygon (polygon1, polygon2 ));
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}



	/**
	 * Non-co-planar triangles. Vertex intersect edges. 
	 */
	void test_pol_pol_10()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1e-54), Value(1e128));
			q1 = Vector<Value> (Value (1e-54), Value(1e-54), Value(1e128));
			r1 = Vector<Value> (Value (2e-54), Value(1e103), Value(1e128));

			p2 = Vector<Value> (Value (0.5e-54), Value(1e-54), Value(1e128));
			q2 = Vector<Value> (Value (3e-54), Value(-1e-54), Value(1e128));
			r2 = Vector<Value> (Value (4e-54), Value(-1e-54), Value(1e-128));


			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));

			CPPUNIT_ASSERT (POINT == res.res_type );
			CPPUNIT_ASSERT (res.point == p2);
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	
	}

	/**
	 * Edge overlap. <p2, q2> overlap with <q1, r1>
	 */	
	void test_pol_pol_11()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1e-54), Value(1e128));
			q1 = Vector<Value> (Value (1e-54), Value(1e-54), Value(1e128));
			r1 = Vector<Value> (Value (2e-54), Value(1e103), Value(1e128));

			p2 = Vector<Value> (Value (2e-54), Value(1e103), Value(1e128));
			q2 = Vector<Value> (Value (1e-54), Value(1e-54), Value(1e128));
			r2 = Vector<Value> (Value (4e-54), Value(-1e-54), Value(1e-128));


			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));

			CPPUNIT_ASSERT (SEGMENT == res.res_type );
			CPPUNIT_ASSERT (res.segment.square_length() == (p2 - q2).square_module());
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}

	/**
	 * Edge halfly overlap. The result is <p2, q2>
	 */
	void test_pol_pol_12()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1e103), Value(1e128));
			q1 = Vector<Value> (Value (1e-54), Value(1e-54), Value(1e128));
			r1 = Vector<Value> (Value (2e-54), Value(1e103), Value(1e128));

			p2 = Vector<Value> (Value (1.5e-54), Value(1e103), Value(1e128));
			q2 = Vector<Value> (Value (1e-54), Value(1e-54), Value(1e128));
			r2 = Vector<Value> (Value (4e-54), Value(-1e-54), Value(1e-128));


			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));

			CPPUNIT_ASSERT (SEGMENT == res.res_type );
			CPPUNIT_ASSERT (res.segment.square_length() == (p2 - q2).square_module());
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}

	/**
	 * Edge partially overlap. The result is <p2, q2>
	 */
	void test_pol_pol_13()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1e103), Value(1e128));
			q1 = Vector<Value> (Value (1e-54), Value(1e-54), Value(1e128));
			r1 = Vector<Value> (Value (2e-54), Value(1e103), Value(1e128));

			p2 = Vector<Value> (Value (1.5e-54), Value(1e103), Value(1e128));
			q2 = Vector<Value> (Value (1.8e-54), Value(1e103), Value(1e128));
			r2 = Vector<Value> (Value (4e-54), Value(-1e-54), Value(1e-128));

			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));

			CPPUNIT_ASSERT (SEGMENT == res.res_type );
			CPPUNIT_ASSERT (res.segment.square_length() == (p2 - q2).square_module());
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}
	/**
	 * Edge overlaps partially. <p2, r1>
	 */
	void test_pol_pol_14()
	{
		try
		{
			Vector<Value> p1, q1, r1 ;  // First triangle. 
			Vector<Value> p2, q2, r2 ;  // Second triangle. 

			p1 = Vector<Value> (Value (0.0), Value(1e103), Value(1e128));
			q1 = Vector<Value> (Value (1e-54), Value(1e-54), Value(1e128));
			r1 = Vector<Value> (Value (2e-54), Value(1e103), Value(1e128));

			p2 = Vector<Value> (Value (1.5e-54), Value(1e103), Value(1e128));
			q2 = Vector<Value> (Value (1.8e-54), Value(1e103), Value(1e-128));
			r2 = Vector<Value> (Value (2.5e-54), Value(1e103), Value(1e128));

			PolygonType polygon1 , polygon2 ;
			polygon1.append_vertex(p1); 
			polygon1.append_vertex(q1); 
			polygon1.append_vertex(r1);

			polygon2.append_vertex(p2); 
			polygon2.append_vertex(q2); 
			polygon2.append_vertex(r2);

			IntersectResult<Value> res; 
			CPPUNIT_ASSERT (true == intersect_tri_tri (polygon1, polygon2, res ));

			CPPUNIT_ASSERT (SEGMENT == res.res_type );
			CPPUNIT_ASSERT (res.segment.square_length() == (p2 - r1).square_module());
		}
		catch (const char * msg)
		{
			std::cerr<<msg<<std::endl;
			throw (msg);			
		}
	}
	void test_pol_pol_15()
	{
	}

private:

};

CPPUNIT_TEST_SUITE_REGISTRATION (Test_intersect);

#endif
